1   /*
2    * Copyright (C) 2012 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import static com.google.common.base.Preconditions.checkNotNull;
20  
21  import com.google.common.annotations.Beta;
22  import com.google.common.annotations.GwtCompatible;
23  
24  import java.util.ArrayDeque;
25  import java.util.Deque;
26  import java.util.Iterator;
27  import java.util.Queue;
28  
29  /**
30   * Views elements of a type {@code T} as nodes in a tree, and provides methods to traverse the trees
31   * induced by this traverser.
32   *
33   * <p>For example, the tree
34   *
35   * <pre>          {@code
36   *          h
37   *        / | \
38   *       /  e  \
39   *      d       g
40   *     /|\      |
41   *    / | \     f
42   *   a  b  c       }</pre>
43   *
44   * <p>can be iterated over in preorder (hdabcegf), postorder (abcdefgh), or breadth-first order
45   * (hdegabcf).
46   *
47   * <p>Null nodes are strictly forbidden.
48   *
49   * @author Louis Wasserman
50   * @since 15.0
51   */
52  @Beta
53  @GwtCompatible(emulated = true)
54  public abstract class TreeTraverser<T> {
55    // TODO(user): make this GWT-compatible when we've checked in ArrayDeque emulation
56  
57    /**
58     * Returns the children of the specified node.  Must not contain null.
59     */
60    public abstract Iterable<T> children(T root);
61  
62    /**
63     * Returns an unmodifiable iterable over the nodes in a tree structure, using pre-order
64     * traversal. That is, each node's subtrees are traversed after the node itself is returned.
65     *
66     * <p>No guarantees are made about the behavior of the traversal when nodes change while
67     * iteration is in progress or when the iterators generated by {@link #children} are advanced.
68     */
69    public final FluentIterable<T> preOrderTraversal(final T root) {
70      checkNotNull(root);
71      return new FluentIterable<T>() {
72        @Override
73        public UnmodifiableIterator<T> iterator() {
74          return preOrderIterator(root);
75        }
76      };
77    }
78  
79    // overridden in BinaryTreeTraverser
80    UnmodifiableIterator<T> preOrderIterator(T root) {
81      return new PreOrderIterator(root);
82    }
83  
84    private final class PreOrderIterator extends UnmodifiableIterator<T> {
85      private final Deque<Iterator<T>> stack;
86  
87      PreOrderIterator(T root) {
88        this.stack = new ArrayDeque<Iterator<T>>();
89        stack.addLast(Iterators.singletonIterator(checkNotNull(root)));
90      }
91  
92      @Override
93      public boolean hasNext() {
94        return !stack.isEmpty();
95      }
96  
97      @Override
98      public T next() {
99        Iterator<T> itr = stack.getLast(); // throws NSEE if empty
100       T result = checkNotNull(itr.next());
101       if (!itr.hasNext()) {
102         stack.removeLast();
103       }
104       Iterator<T> childItr = children(result).iterator();
105       if (childItr.hasNext()) {
106         stack.addLast(childItr);
107       }
108       return result;
109     }
110   }
111 
112   /**
113    * Returns an unmodifiable iterable over the nodes in a tree structure, using post-order
114    * traversal. That is, each node's subtrees are traversed before the node itself is returned.
115    *
116    * <p>No guarantees are made about the behavior of the traversal when nodes change while
117    * iteration is in progress or when the iterators generated by {@link #children} are advanced.
118    */
119   public final FluentIterable<T> postOrderTraversal(final T root) {
120     checkNotNull(root);
121     return new FluentIterable<T>() {
122       @Override
123       public UnmodifiableIterator<T> iterator() {
124         return postOrderIterator(root);
125       }
126     };
127   }
128 
129   // overridden in BinaryTreeTraverser
130   UnmodifiableIterator<T> postOrderIterator(T root) {
131     return new PostOrderIterator(root);
132   }
133 
134   private static final class PostOrderNode<T> {
135     final T root;
136     final Iterator<T> childIterator;
137 
138     PostOrderNode(T root, Iterator<T> childIterator) {
139       this.root = checkNotNull(root);
140       this.childIterator = checkNotNull(childIterator);
141     }
142   }
143 
144   private final class PostOrderIterator extends AbstractIterator<T> {
145     private final ArrayDeque<PostOrderNode<T>> stack;
146 
147     PostOrderIterator(T root) {
148       this.stack = new ArrayDeque<PostOrderNode<T>>();
149       stack.addLast(expand(root));
150     }
151 
152     @Override
153     protected T computeNext() {
154       while (!stack.isEmpty()) {
155         PostOrderNode<T> top = stack.getLast();
156         if (top.childIterator.hasNext()) {
157           T child = top.childIterator.next();
158           stack.addLast(expand(child));
159         } else {
160           stack.removeLast();
161           return top.root;
162         }
163       }
164       return endOfData();
165     }
166 
167     private PostOrderNode<T> expand(T t) {
168       return new PostOrderNode<T>(t, children(t).iterator());
169     }
170   }
171 
172   /**
173    * Returns an unmodifiable iterable over the nodes in a tree structure, using breadth-first
174    * traversal. That is, all the nodes of depth 0 are returned, then depth 1, then 2, and so on.
175    *
176    * <p>No guarantees are made about the behavior of the traversal when nodes change while
177    * iteration is in progress or when the iterators generated by {@link #children} are advanced.
178    */
179   public final FluentIterable<T> breadthFirstTraversal(final T root) {
180     checkNotNull(root);
181     return new FluentIterable<T>() {
182       @Override
183       public UnmodifiableIterator<T> iterator() {
184         return new BreadthFirstIterator(root);
185       }
186     };
187   }
188 
189   private final class BreadthFirstIterator extends UnmodifiableIterator<T>
190       implements PeekingIterator<T> {
191     private final Queue<T> queue;
192 
193     BreadthFirstIterator(T root) {
194       this.queue = new ArrayDeque<T>();
195       queue.add(root);
196     }
197 
198     @Override
199     public boolean hasNext() {
200       return !queue.isEmpty();
201     }
202 
203     @Override
204     public T peek() {
205       return queue.element();
206     }
207 
208     @Override
209     public T next() {
210       T result = queue.remove();
211       Iterables.addAll(queue, children(result));
212       return result;
213     }
214   }
215 }